package com.xiaohui.gwc.utils;

/**
 * @Author: Poppin
 * @Date: 2021/11/30 12:35
 * @Version: 1.0
 */
public class SnowIdUtils {

    private static class SnowFlake{

        private static final SnowFlake SNOW_FLAKE= new SnowFlake();

        private final long START_TIMESTAMP = 1557489395327L;

        private final long SEQUENCE_BIT = 12;
        private final long MACHINE_BIT = 0;
        private final long TIMESTAMP_LEFT = SEQUENCE_BIT+MACHINE_BIT;
        private final long MAX_SEQUENCE=~(-1L << SEQUENCE_BIT);
        private final long MAX_MACHINE_ID = ~(-1L << MACHINE_BIT);
        private long machineIdPart;
        private long sequence = 0L;
        private long lastStamp = -1L;
        private SnowFlake(){
            long localIp = 4321;
            machineIdPart=(localIp&MAX_MACHINE_ID)<<SEQUENCE_BIT;
        }
        public synchronized long nextId(){
            long currentStamp = timeGen();
            while (currentStamp<lastStamp){
                throw new RuntimeException(String.format("时钟已经回拨. Refusing to generate id for %d milliseconds",lastStamp-currentStamp));
            }
            if (currentStamp==lastStamp){
                sequence = (sequence+1)&MAX_SEQUENCE;
                if (sequence==0){
                    currentStamp=getNextMIll();
                }
            }else {
                sequence=0L;
            }
            lastStamp=currentStamp;
            return (currentStamp-START_TIMESTAMP)<<TIMESTAMP_LEFT|machineIdPart|sequence;
        }

        private long getNextMIll(){
            long mill = timeGen();
            while (mill<=lastStamp){
                mill=timeGen();
            }
            return mill;
        }
        protected long timeGen(){
            return System.currentTimeMillis();
        }
    }

    //返回类型Long
    public static long uniqueLong(){
        return SnowFlake.SNOW_FLAKE.nextId();
    }

    //返回类型为String
    public static String uniqueLongHex(){
        return String.format("%016x",uniqueLong());
    }
}

